import hashlib
import os
import shutil
import tempfile
from tkinter import messagebox

import PIL
import PIL.ExifTags
import win32com.client as win32
from PIL import Image, ImageOps
from docx import Document
from docx.enum.section import WD_ORIENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.ns import qn
from docx.shared import Inches, Pt


class ImageProcessorController:
    """图片处理器控制器"""

    def __init__(self, model):
        self.model = model

    def compress_images_batch(self, file_paths):
        """批量压缩图片到临时目录"""
        compressed_files = []

        # 创建临时目录存储压缩后的图片
        temp_dir = os.path.join(tempfile.gettempdir(), "image_tool_compressed")
        os.makedirs(temp_dir, exist_ok=True)

        for idx, file_path in enumerate(file_paths):
            try:
                # 生成压缩文件路径
                hash_str = hashlib.md5(file_path.encode()).hexdigest()
                compressed_path = os.path.join(temp_dir, f"{hash_str}_compressed.jpg")

                # 如果已经压缩过，直接使用
                if os.path.exists(compressed_path):
                    compressed_files.append(compressed_path)
                    continue

                # 打开并压缩图片
                with Image.open(file_path) as img:
                    # 应用旋转
                    img = ImageOps.exif_transpose(img)

                    # 转换为RGB（如果需要）
                    if img.mode in ('RGBA', 'LA', 'P'):
                        # 创建白色背景
                        background = Image.new('RGB', img.size, (255, 255, 255))
                        if img.mode == 'P':
                            img = img.convert('RGBA')
                        background.paste(img, mask=img.split()[-1] if img.mode in ('RGBA', 'LA') else None)
                        img = background
                    elif img.mode != 'RGB':
                        img = img.convert('RGB')

                    # 限制最大尺寸
                    max_size = 1920  # 可以根据需要调整
                    if max(img.size) > max_size:
                        img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)

                    # 保存压缩后的图片
                    img.save(compressed_path, 'JPEG', quality=85, optimize=True)

                    # 保存原始文件路径作为元数据
                    with open(compressed_path + '.meta', 'w') as f:
                        f.write(file_path)

                    compressed_files.append(compressed_path)

            except Exception as e:
                self.model.logger.error(f"压缩图片失败 {file_path}: {str(e)}")
                # 如果压缩失败，使用原始文件
                compressed_files.append(file_path)

        return compressed_files

    def apply_rotation(self, img):
        """根据EXIF信息自动旋转图片至正确方向"""
        try:
            exif = img._getexif()
            if exif:
                for tag, value in exif.items():
                    decoded = PIL.ExifTags.TAGS.get(tag, tag)
                    if decoded == "Orientation":
                        orientation = value
                        break
                else:
                    orientation = None
            else:
                orientation = None

            if orientation == 3:
                img = img.rotate(180, expand=True)
            elif orientation == 6:
                img = img.rotate(270, expand=True)
            elif orientation == 8:
                img = img.rotate(90, expand=True)
        except (AttributeError, KeyError, IndexError):
            pass
        return img

    def process_dropped_files(self, output_dir):
        """处理已压缩的图片文件"""
        img_files = []

        for file_path in self.model.dropped_files:
            try:
                # 获取原始文件名
                original_path = self.model.get_original_path(file_path)
                filename = os.path.basename(original_path)

                # 如果是压缩文件，直接复制
                if file_path.endswith('_compressed.jpg'):
                    new_path = os.path.join(output_dir, filename.rsplit('.', 1)[0] + '.jpg')
                    shutil.copy2(file_path, new_path)
                    img_files.append(new_path)
                else:
                    # 原有的处理逻辑（用于未压缩的文件）
                    img = Image.open(file_path)
                    img = self.apply_rotation(img)

                    if img.width > 2000:
                        ratio = 2000 / img.width
                        new_height = int(img.height * ratio)
                        img = img.resize((2000, new_height), Image.LANCZOS)

                    format = "PNG" if img.mode in ("RGBA", "LA") or (
                            img.mode == "P" and "transparency" in img.info) else "JPEG"
                    ext = ".png" if format == "PNG" else ".jpg"

                    new_path = os.path.join(output_dir, filename)
                    img.save(new_path, format=format, quality=90)
                    img_files.append(new_path)

            except Exception as e:
                messagebox.showwarning("图片处理警告", f"{filename} 处理失败，使用原始文件: {str(e)}")
                shutil.copy2(original_path, os.path.join(output_dir, filename))
                img_files.append(os.path.join(output_dir, filename))

        return img_files

    def create_word_document(self, output_dir, img_files, folder_name, template_path):
        """创建Word文档"""
        doc_name = f"{folder_name}.docx"
        doc_path = os.path.join(output_dir, doc_name)
        shutil.copy2(template_path, doc_path)

        doc = Document(doc_path)

        # 修改页脚
        for section in doc.sections:
            for footer in [section.footer]:
                for paragraph in footer.paragraphs:
                    paragraph.text = folder_name
                    for run in paragraph.runs:
                        run.font.size = Pt(16)
                        run.font.name = "仿宋_GB2312"
                        r = run._element.rPr.rFonts
                        r.set(qn("w:eastAsia"), "仿宋_GB2312")

        # 删除末尾空段落
        if len(doc.paragraphs) > 0:
            last_paragraph = doc.paragraphs[-1]
            if not last_paragraph.text.strip():
                p = last_paragraph._element
                p.getparent().remove(p)

        # 插入图片
        for img_file in img_files:
            try:
                section = doc.sections[0]
                is_landscape = section.orientation == WD_ORIENT.LANDSCAPE

                top_margin = section.top_margin.cm
                bottom_margin = section.bottom_margin.cm
                header_distance = section.header_distance.cm
                footer_distance = section.footer_distance.cm

                if is_landscape:
                    max_width_cm = 29.7 - section.left_margin.cm - section.right_margin.cm
                    max_height_cm = 21.0 - top_margin - bottom_margin - header_distance - footer_distance
                else:
                    max_width_cm = 21.0 - section.left_margin.cm - section.right_margin.cm
                    max_height_cm = 29.7 - top_margin - bottom_margin - header_distance - footer_distance

                max_width_cm = max(max_width_cm, 5.0)
                max_height_cm = max(max_height_cm, 5.0)

                max_width_inch = Inches(max_width_cm / 2.54)
                max_height_inch = Inches(max_height_cm / 2.54)

                with Image.open(img_file) as img:
                    img_width, img_height = img.size
                    aspect_ratio = img_width / img_height

                    if aspect_ratio > 1:
                        height_by_width = max_height_inch * (max_width_inch / max_height_inch) / aspect_ratio
                        width_by_height = max_width_inch * (aspect_ratio * max_height_inch / max_width_inch)
                        if height_by_width <= max_height_inch:
                            width = max_width_inch
                            height = height_by_width
                        else:
                            height = max_height_inch
                            width = width_by_height
                    else:
                        height = max_height_inch
                        width = height * aspect_ratio

                paragraph = doc.add_paragraph()
                paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
                run = paragraph.add_run()
                run.add_picture(img_file, width=width)
                doc.add_paragraph()

            except Exception as e:
                messagebox.showwarning("图片插入失败", f"无法插入图片 {os.path.basename(img_file)}: {str(e)}")

        # 删除最后一个空段落
        if len(doc.paragraphs) > 0:
            last_paragraph = doc.paragraphs[-1]
            if not last_paragraph.text.strip():
                p = last_paragraph._element
                p.getparent().remove(p)

        doc.save(doc_path)

        # 使用win32com确保格式正确
        try:
            word = win32.gencache.EnsureDispatch("Word.Application")
            word.Visible = False
            doc = word.Documents.Open(os.path.abspath(doc_path))
            doc.Save()
            doc.Close()
            word.Quit()
        except:
            pass

        return doc_path
